#include <stdio.h>
#include <stdlib.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <rte_malloc.h>
#include <rte_timer.h>

#define NUM_MBUFS (8192-1)
int gDpdkPortId = 0;   // 逻辑数值，绑定网口第一个就是0，

static const struct rte_eth_conf port_conf_default = {.rxmode = {.max_lro_pkt_size = RTE_ETHER_MAX_LEN}};  // 最大的rx包

static uint8_t g_default_arp_mac[RTE_ETHER_ADDR_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

static void init_port(struct rte_mempool * m_pool){
    // 获取可用的以太网设备数量;返回的设备数量仅表示已注册并准备就绪的设备，不一定代表所有物理或虚拟接口
    uint16_t sys_ports = rte_eth_dev_count_avail();    // 绑定适配器网卡数量， 网口数量
    printf("sys_ports : %d \n", sys_ports);

    struct rte_eth_dev_info dev_info;  // 获取网卡配置信息 eth0
    rte_eth_dev_info_get(gDpdkPortId, &dev_info);

    const int num_rx_queues = 1;  // 配置几个接收队列： 小于 8
    const int num_tx_queues = 1;  // 发送
    struct rte_eth_conf port_conf = port_conf_default;  // 接收每一帧接收数据最大数量
    // 设置网卡设备 rx tx 队列 以及相关参数
    rte_eth_dev_configure(gDpdkPortId, num_rx_queues, num_tx_queues, &port_conf);
    // rte_eth_rx_queue_setup 给指定的网卡 设置接收队列，
    /*
port_id: 以太网端口的标识符。
queue_id: 接收队列的 ID。
nb_desc: 接收队列中要分配的描述符数量。描述符是用于指向接收到的数据包缓冲区的数据结构，更多的描述符可以提高并发处理能力。
socket_id: 用于分配接收队列内存资源的 NUMA 节点 ID。这允许用户根据系统架构优化内存访问。例如，如果你的应用程序和数据运行在同一 NUMA 节点上，可以选择对应节点的 ID。
rx_conf: 指向 rte_eth_rxconf 结构体的指针，该结构体包含了特定于接收队列的一些配置选项，如启用/禁用某些功能等。如果该参数为 NULL，则使用默认值进行配置。
mb_pool: 指向 rte_mempool 的指针，表示将用于存储接收到的数据包缓冲区。这个内存池应该在调用此函数之前创建，并确保有足够数量的数据包缓冲区可供使用
    */
    if(rte_eth_rx_queue_setup(gDpdkPortId, 0, 1024, rte_eth_dev_socket_id(gDpdkPortId), NULL, m_pool) < 0){
        printf("rte_eth_rx_queue_setup \n");
    }

    struct rte_eth_txconf tx_conf = dev_info.default_txconf;
    tx_conf.offloads = port_conf.rxmode.offloads;
    // 网口id ， 接收队列id， 队列长度
    if(rte_eth_tx_queue_setup(gDpdkPortId, 0, 1024, rte_eth_dev_socket_id(gDpdkPortId), &tx_conf) < 0){
        printf("rte_eth_tx_queue_setup \n");
    }
    if(rte_eth_dev_start(gDpdkPortId) < 0){   // 启动指定的以太网设备，使其开始接收和发送数据包
        printf("rte_eth_dev_start \n");
    }
// 启用指定以太网端口的混杂模式。
//混杂模式允许网络接口接收所有经过的数据包，而不仅仅是发往该接口的数据包。这对于流量监控、数据包捕获和分析非常有用
    rte_eth_promiscuous_enable(gDpdkPortId);
}




//   193.168.3.66
int main(int argc, char * argv[]){
    if(rte_eal_init(argc, argv) < 0){ printf("rte_eal_init \n"); }
    // mbuf pool ；  mbuf 相当于 sk_buf, 预分配一定数量的mbuf
    // rte_socket_id()  当前那块内存分配的
    // 创建一个专门用于存储网络数据包的内存池。
    // 该内存池中的每个元素是一个 rte_mbuf 结构，用于存储网络数据包及其元数据
    // 内存池可以绑定到特定的 NUMA 节点，确保内存分配在本地节点，减少跨节点访问的开销。
    struct rte_mempool * m_pool = rte_pktmbuf_pool_create("m_pool",NUM_MBUFS,0,0,
                                                          RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
    if(m_pool == NULL){ printf("m_pool == NULL \n"); }

    init_port(m_pool);



    return 0;
}

